package jp.sourceforge.akjrcp.ffmpeg;

import com.akjava.lib.standards.process.ProcessMonitor;
import com.akjava.lib.standards.process.ProcessPrinter;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import jp.sourceforge.akjrcp.ui.DirectryBasedExecuterListener;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class InputStreamFFMpegExecuter {
public static Log log = LogFactory.getLog(InputStreamFFMpegExecuter.class);



private FFMpegPreference ffmpegPreference=new FFMpegPreference();
private Process process;
private boolean cancelling;

private DirectryBasedExecuterListener executeListener;

private List inputFiles=new ArrayList();

private File outputFile;

public int getGuessSize(){
	return ffmpegPreference.getGuessSize();
}


public void cancel(){
	log.info("called cancel");
	synchronized(this){
		log.info("cancell:"+System.currentTimeMillis());
		cancelling=true;
		}
	if(process!=null){
		process.destroy();
		log.info("maybe destroyed:"+process);
	}
	
}


public static File makeBackupFile(File file,String addextension){
	int count=1;
	File bkfile=new File(file.getParentFile(),file.getName()+"."+addextension);
	while(bkfile.exists()){
		bkfile=new File(file.getParentFile(),file.getName()+"."+"("+count+")."+addextension);
		count++;
	}
	return bkfile;
}

private void inExecute(){
	
	
	
	File tmpOutput=outputFile;
	if(tmpOutput==null){
		return;//do somethin faild;
	}
	
	File input=null;
	
	
	
	
	
	if(process!=null){
		//anyway old process must die.
		process.destroy();
	}
	
	process = null;
	
	
	
	
	//tmpOutput.getParentFile().mkdirs();//need?
	try {
		if(!ffmpegPreference.isTwoPassEncode()){
			//log.info(input.getAbsolutePath()+avsPath+tmpOutput.getAbsolutePath());
			
			
		
		//null is input
		String[] commands=ffmpegPreference.toCommand("-",null,tmpOutput.getAbsolutePath());
		if(commands==null){
			log.warn("null command");
			return;
		}
		
		if(executeListener!=null){
			executeListener.startConvert(null);
		}
		
		Runtime runtime=Runtime.getRuntime();

		ProcessPrinter printer=new ErrorCatchProcessPrinter();
		try {
			printer.printOutput(toDebugArray(commands));
		} catch (IOException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
		log.info("start process:"+process+","+ArrayUtils.toString(commands));
		
		
		
		
		process = runtime.exec(commands);
		
		//log.info("start process:"+process+","+ArrayUtils.toString(commands));
		log.info("process:"+System.currentTimeMillis()+","+cancelling);
		
		ProcessMonitor monitor=new ProcessMonitor(process,printer);
		monitor.startMonitor();
		
		//TODO
		//open input stream and write all files.
		writeInFiles(process);
		
		try {
			if(!cancelling){
			process.waitFor();
			}else{
			log.info("finally cancel ");
			return;
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		}else{
			throw new RuntimeException("2pass not supported");
		}
	} catch (IOException e1) {
		//maybe catch not supported codecs.
		e1.printStackTrace();
		process.destroy();
		if(executeListener!=null){
			executeListener.faildConvert(null,e1.getMessage());
			}
		return;
	}
	
	//call finish
	if(executeListener!=null){
		executeListener.endConvert(null);
		}
	
	process=null;
	//cancelling=false; damm.this time cancell all only.
}
public void writeInFiles(Process process){
	//do all file.
	
}

public class TestMonitor implements DirectryBasedExecuterListener{

	public void beforeConvert() {
		// TODO Auto-generated method stub
		
	}

	public void afterConvert() {
		// TODO Auto-generated method stub
		
	}

	public void startConvert(File file) {
		// TODO Auto-generated method stub
		
	}

	public void endConvert(File file) {
		// TODO Auto-generated method stub
		
	}

	public void faildConvert(File file, String message) {
		log.info("faild:"+file);
	}

	public void printProcess(String line) {
		// TODO Auto-generated method stub
		
	}

	public boolean askOverwrite(File output) {
		// TODO Auto-generated method stub
		return false;
	}
	
}

public static String toDebugArray(String[] array){
	String v="";
	for (int i = 0; i < array.length; i++) {
		v+="\""+array[i]+"\""+" ";
	}
	return v+"\n";
}



public DirectryBasedExecuterListener getExecuteListener() {
	return executeListener;
}

public void setExecuteListener(DirectryBasedExecuterListener executeListener) {
	this.executeListener = executeListener;
}



public FFMpegPreference getFfmpegPreference() {
	return ffmpegPreference;
}

public void setFfmpegPreference(FFMpegPreference ffmpegPreference) {
	this.ffmpegPreference = ffmpegPreference;
}


public class ErrorCatchProcessPrinter implements ProcessPrinter{
	public void printOutput(String output) throws IOException {
		print(output);
	}

	public void printError(String error)  throws IOException{
		print(error);
	}

	private void print(String line) throws IOException{
		if(executeListener!=null){
			executeListener.printProcess(line);
			}
		log.debug(line);
		
		if(line.indexOf(DirectryBasedExecuterListener.ERROR_NOTSUPPORTED_VIDEO)!=-1){
			//cancel();
			throw new IOException(DirectryBasedExecuterListener.ERROR_NOTSUPPORTED_VIDEO);
		}
		
	}
	
}

public void addFile(File file){
	inputFiles.add(file);
}

}
